package cn.lll.vuehouse.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.lll.vuehouse.FORM.UserLoginForm;
import cn.lll.vuehouse.common.ResponseResult;
import cn.lll.vuehouse.common.ResponseStatus;
import cn.lll.vuehouse.dto.UserDto;
import cn.lll.vuehouse.entity.*;
import cn.lll.vuehouse.mapper.*;
import cn.lll.vuehouse.service.UserService;
import cn.lll.vuehouse.utils.JWTUtil;
import cn.lll.vuehouse.vo.UserVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author asus-pc
 * @description 针对表【sys_user】的数据库操作Service实现
 * @createDate 2023-09-01 11:34:23
 */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {


    @Autowired
    UserMapper userMapper;

    @Autowired
    DeptMapper deptMapper;

    @Autowired
    UserRoleMapper userRoleMapper;


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public ResponseResult login(UserLoginForm userLoginForm, HttpServletRequest httpServletRequest) {
        ResponseResult responseResult = new ResponseResult();

        //1.判定验证码
        String code = userLoginForm.getCode();
        String imguuid = userLoginForm.getImguuid();
        //更具uuid  获取redis中缓存的验证码
        String captcha = stringRedisTemplate.opsForValue().get(imguuid);

        //比较captcha 时效性  code
        if (StringUtils.isEmpty(captcha)) {
            responseResult.fail(ResponseStatus.CODE_EXPIRE);
            return responseResult;
        }

        if (!StringUtils.equals(code, captcha)) {
            responseResult.fail(ResponseStatus.CODE_ERROR);
            return responseResult;
        }

        //2.验证码判定通过   根据用户名查询用户信息
        String username = userLoginForm.getUsername();
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.eq(User::getName, username);
        User user = userMapper.selectOne(lambda);

        //判断用户是否存在
        if (ObjectUtil.isEmpty(user)) {
            throw new UnknownAccountException("用户不存在");
        }

        //判定密码是否正确
        String salt = user.getSalt();
        System.out.println("salt = " + salt);
        System.out.println(userLoginForm.getPassword());
        String md5Pwd = new Md5Hash(userLoginForm.getPassword(), salt, 1024).toHex();
        System.out.println("md5Pwd = " + md5Pwd);
        String password = user.getPwd();
        System.out.println("password = " + password);
        if (!StringUtils.equals(md5Pwd, password)) {
            throw new IncorrectCredentialsException("密码错误");
        }

        //判断用户状态是否可用
        Integer state = user.getAvailable();
        if (state == 0) {
            throw new LockedAccountException("账户禁用");
        }

        //3.登录成功  生成token  返回前端
        HashMap<String, Object> claims = new HashMap<>();
        claims.put("username", user.getName());
        claims.put("userId", user.getId());
        String token = JWTUtil.createToken(claims);


//        登录日志操作
//        LogInfo logInfo = new LogInfo();
//        logInfo.setUsername(user.getUsername());
//        logInfo.setIp(IpUtil.getIp(httpServletRequest));
//        logInfo.setModel("登录模块");
//        logInfo.setDescription("登录操作");
//
//
//
//
//        logInfoService.saveOrUpdate(logInfo);


        //需要返回前端的数据
        HashMap<String, Object> data = new HashMap<>();
        data.put("token", token);
        data.put("nickName", user.getLoginname());
        responseResult.success(ResponseStatus.LOGIN_SUCCESS, data);
        return responseResult;
    }

    @Override
    public ResponseResult getMenu(HttpServletRequest request) {
        ResponseResult responseResult = new ResponseResult();

        String token = request.getHeader("token");
        // 从token中获取用户id
        Integer userId = (Integer) JWTUtil.getClaim(token).get("userId");

        // 根据用户id查询用户角色关联表获取rid
        LambdaQueryWrapper<UserRole> userRoleLambda = new QueryWrapper<UserRole>().lambda();
        userRoleLambda.eq(UserRole::getUid,userId);
        List<Integer> rids = userRoleMapper.selectList(userRoleLambda).stream().map(ur -> ur.getRid()).collect(Collectors.toList());

        // 根据rid查询角色权限关联表获取pid
        LambdaQueryWrapper<RolePermission> lambda = new QueryWrapper<RolePermission>().lambda();
        lambda.in(RolePermission::getRid,rids);
        Set<Integer> pids = rolePermissionMapper.selectList(lambda).stream().map(rp -> rp.getPid()).collect(Collectors.toSet());

        // 判断pids是否为空
        if(pids.size()==0){
            responseResult.success(ResponseStatus.SUCCESS,new ArrayList<>());
            return responseResult;
        }

        // 根据pid查询权限表获取  排除按钮
        LambdaQueryWrapper<Permission> lambda1 = new QueryWrapper<Permission>().lambda();
        lambda1.in(Permission::getId,pids)
                .ne(Permission::getIsMenu,2);
        List<Permission> permissions = permissionMapper.selectList(lambda1);

        responseResult.success(ResponseStatus.SUCCESS,permissions);


        return responseResult;
    }

    @Override
    public ResponseResult getCurrentPageUserInfo(UserDto userDto) throws InvocationTargetException, IllegalAccessException {
        Page<User> userPage = new Page<>(userDto.getCurrentPage(), userDto.getPageSize());
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq(StringUtils.isNotEmpty(userDto.getName()), "name", userDto.getName())
                .eq(ObjectUtil.isNotEmpty(userDto.getAvailable()), "available", userDto.getAvailable());
        userMapper.selectPage(userPage, userQueryWrapper);
        List<User> records = userPage.getRecords();
        long count = userPage.getTotal();
        HashMap<String, Object> map = new HashMap<>();
        ArrayList<UserVo> userVos = new ArrayList<>();
        for (User record : records) {
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(userVo, record);
            QueryWrapper<Dept> deptQueryWrapper = new QueryWrapper<>();
            deptQueryWrapper.eq("id", record.getDeptid());
            String deptName = deptMapper.selectOne(deptQueryWrapper).getName();
            userVo.setDeptName(deptName);
            userVos.add(userVo);
        }
        map.put("data", userVos);
        map.put("count", count);
        ResponseResult responseResult = new ResponseResult();
        responseResult.success(ResponseStatus.SUCCESS, map);
        return responseResult;
    }

    @Override
    public ResponseResult getFullUserInfo(Integer id) throws InvocationTargetException, IllegalAccessException {
        ResponseResult responseResult = new ResponseResult();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id", id);
        User user = userMapper.selectOne(userQueryWrapper);
        QueryWrapper<Dept> deptQueryWrapper = new QueryWrapper<>();
        deptQueryWrapper.eq("id", user.getDeptid());
        String deptName = deptMapper.selectOne(deptQueryWrapper).getName();
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(userVo, user);
        userVo.setDeptName(deptName);
        responseResult.success(ResponseStatus.SUCCESS, userVo);
        return responseResult;
    }

    @Override
    public ResponseResult changeUserAvailable(User user) {
        ResponseResult responseResult = new ResponseResult();
        userMapper.updateById(user);
        responseResult.success(ResponseStatus.SUCCESS);
        return responseResult;
    }

    @Override
    public ResponseResult batchDeleteUser(List<Integer> ids) {
        ResponseResult responseResult = new ResponseResult();
        userMapper.deleteBatchIds(ids);
        // 删除用户所对应的角色
        ids.forEach(id -> {
            QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
            userRoleQueryWrapper.eq(ObjectUtils.isNotEmpty(id),"uid", id);
            userRoleMapper.delete(userRoleQueryWrapper);
        });
        responseResult.success(ResponseStatus.SUCCESS);
        return responseResult;
    }

    @Override
    public ResponseResult addAndUpdateUser(User user) {
        ResponseResult responseResult = new ResponseResult();
        if(ObjectUtils.isNotEmpty(user.getId())){ // 更新
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("name", user.getName())
                    .ne("id", user.getId());
            User user1 = userMapper.selectOne(userQueryWrapper);
            if(ObjectUtil.isNotEmpty(user1)){
                responseResult.success(ResponseStatus.USER_EXIST);
                return responseResult;
            }
            userMapper.updateById(user);
            responseResult.success(ResponseStatus.SUCCESS);
            return responseResult;
        }
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("name", user.getName());
        User user1 = userMapper.selectOne(userQueryWrapper);
        if(ObjectUtil.isNotEmpty(user1)){
            responseResult.success(ResponseStatus.USER_EXIST);
        }
        userMapper.insert(user);
        responseResult.success(ResponseStatus.SUCCESS);
        return responseResult;
    }

}




